﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SegIdenPC.Entidad;
using log4net;
using SegIdenPC.Herramientas;
using GS1.Utilitario;

namespace SegIdenPC.Formularios
{
    public partial class frmVenta : Form
    {
        #region --- Variables y Propiedades ---
        private static readonly ILog log = LogManager.GetLogger(typeof(frmVenta));

        private const string TITULO = "Generar Venta";

        private const string FORMATO_PRODUCTO_DESCRIPCION_DETALLADA = "{0} - {1} - {2} - {3}";

        private Double igvActual = 0.18;
        
        private Cliente clienteActual = null;

        private Producto producto = null;

        public Cliente clienteFormulario { get; set; }

        public ListaItem listaItemFormulario { get; set; }

        public bool formularioVentaImportada { get; set; }

        #endregion

        #region --- Constructor ---
        public frmVenta()
        {
            InitializeComponent();
        }
        #endregion

        #region --- Eventos Formulario ---
        private void frmVenta_Load(object sender, EventArgs e)
        {
            cargarFormulario();
        }

        private void tbtnNuevo_Click(object sender, EventArgs e)
        {
            nuevo();
        }

        private void tbtnGrabar_Click(object sender, EventArgs e)
        {
            grabar();
        }

        private void tbtnSalir_Click(object sender, EventArgs e)
        {
            salir();
        }

        private void btnAgregar_Click(object sender, EventArgs e)
        {
            agregarItem();
        }

        private void btnEliminar_Click(object sender, EventArgs e)
        {
            quitarItem();
        }

        private void btnBuscarCliente_Click(object sender, EventArgs e)
        {
            elegirCliente();
        }

        private void btnBuscarProducto_Click(object sender, EventArgs e)
        {
            elegirProducto();
        }

        private void txtProductoPrecio_KeyPress(object sender, KeyPressEventArgs e)
        {
            Libreria.SoloNumeros((TextBox)sender, e, true, 2);
        }

        private void txtClienteNroDocumento_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter) { buscarCliente(); }
        }

        private void txtClienteNroDocumento_TextChanged(object sender, EventArgs e)
        {
            limpiarDatosCliente();
        }

        private void cboTipoDocumento_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (this.cboTipoDocumento.Focused) { limpiarDatosCliente(); }
        }
        #endregion

        #region --- Metodos Propios ---
        private T ejecutarOperacionGenerico<T>(Operacion operacion)
        {
            string contenidoXML = string.Empty;

            // Instanciando y ejecutando llamada al ServicioREST
            ConexionREST conexionREST = new ConexionREST();
            contenidoXML = conexionREST.ejecutarOperacion(operacion);

            // Obteniendo Objeto de Error
            OperacionError operacionError = contenidoXML.DeserializarTo<OperacionError>();

            // Validar si hay error
            if (operacionError != null)
            {
                Libreria.ShowMessageboxError(operacionError.descripcion);
                return default(T);
            }

            return contenidoXML.DeserializarTo<T>();
        }

        private void cargarMonedas()
        {
            ListaMoneda listaMoneda = null;

            // Estableciendo operacion a ser enviada al Servicio REST
            Operacion operacion = new Operacion();
            operacion.numero = Constantes.OPERACION_LISTAR_MONEDAS;

            listaMoneda = ejecutarOperacionGenerico<ListaMoneda>(operacion);
            if (listaMoneda == null) { return; }

            // Estableciendo listado de paises
            this.cboMoneda.DataSource = listaMoneda.lista;
            this.cboMoneda.ValueMember = Constantes.GENERAL_CODIGO;
            this.cboMoneda.DisplayMember = Constantes.GENERAL_DESCRIPCION;
            this.cboMoneda.SelectedIndex = 0;
        }

        private void cargarTipoDocumentoVenta()
        {
            ListaTipoDocumentoVenta listaTipoDocumentoVenta;

            // Estableciendo operacion a ser enviada al Servicio REST
            Operacion operacion = new Operacion();
            operacion.numero = Constantes.OPERACION_LISTAR_TIPO_DOCUMENTO_VENTA;

            listaTipoDocumentoVenta = ejecutarOperacionGenerico<ListaTipoDocumentoVenta>(operacion);
            if (listaTipoDocumentoVenta == null) { return; }

            // Estableciendo parametros del combo Tipo doc venta
            this.cboTipoDocVenta.DataSource = listaTipoDocumentoVenta.lista;
            this.cboTipoDocVenta.ValueMember = Constantes.GENERAL_CODIGO;
            this.cboTipoDocVenta.DisplayMember = Constantes.GENERAL_DESCRIPCION;
            this.cboTipoDocVenta.SelectedIndex = 0;
        }

        private void cargarFormaVenta()
        {
            ListaFormaVenta listaFormaVenta = null;

            // Estableciendo operacion a ser enviada al Servicio REST
            Operacion operacion = new Operacion();
            operacion.numero = Constantes.OPERACION_LISTAR_FORMA_VENTA;

            listaFormaVenta = ejecutarOperacionGenerico<ListaFormaVenta>(operacion);
            if (listaFormaVenta == null) { return; }

            // Estableciendo parametros del combo forma de pago
            this.cboFormaVenta.DataSource = listaFormaVenta.lista;
            this.cboFormaVenta.ValueMember = Constantes.GENERAL_CODIGO;
            this.cboFormaVenta.DisplayMember = Constantes.GENERAL_DESCRIPCION;
            this.cboFormaVenta.SelectedIndex = 0;
        }

        private void cargarFormulario()
        {
            ListaGeneral listaTipoDocumento = null;

            try
            {
                Cursor.Current = Cursors.WaitCursor;
                cargarFormaVenta();
                cargarTipoDocumentoVenta();
                cargarMonedas();

                this.igvActual = cargarIgv();

                // Instanciando y creando listado de documentos
                listaTipoDocumento = new ListaGeneral();
                listaTipoDocumento.Add(new General { codigo = Constantes.CODIGO_TIPO_DOCUMENTO_DNI, descripcion = Constantes.DESCRIPCION_TIPO_DOCUMENTO_DNI });
                listaTipoDocumento.Add(new General { codigo = Constantes.CODIGO_TIPO_DOCUMENTO_RUC, descripcion = Constantes.DESCRIPCION_TIPO_DOCUMENTO_RUC });
                listaTipoDocumento.Add(new General { codigo = Constantes.CODIGO_TIPO_DOCUMENTO_CE, descripcion = Constantes.DESCRIPCION_TIPO_DOCUMENTO_CE });
                listaTipoDocumento.Add(new General { codigo = Constantes.CODIGO_TIPO_DOCUMENTO_CI, descripcion = Constantes.DESCRIPCION_TIPO_DOCUMENTO_CI });

                // Estableciendo parametros del combo Tipo documento
                this.cboTipoDocumento.DataSource = listaTipoDocumento;
                this.cboTipoDocumento.ValueMember = Constantes.GENERAL_CODIGO;
                this.cboTipoDocumento.DisplayMember = Constantes.GENERAL_DESCRIPCION;
                this.cboTipoDocumento.SelectedIndex = 0;

                this.txtSerie.Focus();

                if (formularioVentaImportada)
                {
                    this.clienteActual = this.clienteFormulario;
                    this.cboTipoDocumento.Text = this.clienteActual.tipoDocumento;
                    this.txtClienteNroDocumento.Text = this.clienteActual.nroDocumento;
                    this.txtClienteRazonSocial.Text = this.clienteActual.razonSocial;

                    // Se establece propiedad para evitar que genere nuevas columnas que no estan mapeadas en la grilla
                    this.dgvListadoItemsSeleccionados.AutoGenerateColumns = false;
                    //Listado temporal para poder cambiar el estado de los items
                    ListPersonalizada<Item> listaItemsSeleccion = new ListPersonalizada<Item>();

                    foreach (Item itemFormulario in this.listaItemFormulario.lista)
                    {
                        itemFormulario.estado = Constantes.ESTADO_ITEM_VENDIDO;
                        itemFormulario.precioVenta = itemFormulario.producto.precioVentaMaximo;
                        itemFormulario.producto.precioVentaTransaccion = itemFormulario.producto.precioVentaMaximo;
                        itemFormulario.producto.precioVentaTransaccion = itemFormulario.precioCompra;

                        listaItemsSeleccion.Add(itemFormulario);
                    }
                    // Actualizando en grilla
                    this.dgvListadoItemsSeleccionados.DataSource = null;
                    this.dgvListadoItemsSeleccionados.DataSource = listaItemsSeleccion;

                    pintarGrilla(this.dgvListadoItemsSeleccionados);

                    // Recalcular total
                    calcularTotal();
                }

            }
            catch (Exception ex)
            {
                log.Error(ex.Message, ex);
                Libreria.MensajeError(ex, TITULO);
            }
            finally
            {
                Cursor.Current = Cursors.Default;
            }
        }

        private void elegirCliente()
        {
            using (frmMantCliente frmMantCliente = new frmMantCliente())
            {
                frmMantCliente.formularioBusqueda = true;
                if (frmMantCliente.ShowDialog() == DialogResult.Cancel) { return; }

                this.clienteActual = frmMantCliente.clienteActual;
                this.cboTipoDocumento.Text = this.clienteActual.tipoDocumento;
                this.txtClienteNroDocumento.Text = this.clienteActual.nroDocumento;
                this.txtClienteRazonSocial.Text = this.clienteActual.razonSocial;
            }
        }

        private bool validarEntradaBusqueda()
        {
            this.txtClienteNroDocumento.Text = this.txtClienteNroDocumento.Text.Trim();

            if (this.txtClienteNroDocumento.Text.Equals(string.Empty))
            {
                Libreria.CampoNecesario(this.txtClienteNroDocumento, "Debes ingresa el número de documento");
                return true;
            }

            if (this.txtClienteNroDocumento.TextLength < 3)
            {
                Libreria.CampoNecesario(this.txtClienteNroDocumento, "Debe ingresar por lo menos 3 caracteres para realizar la busqueda");
                return true;
            }

            return false;
        }

        private void buscarCliente()
        {
            Operacion operacion = null;
            string contenidoXML = string.Empty;

            try
            {
                if (validarEntradaBusqueda()) { return; }

                Cursor.Current = Cursors.WaitCursor;

                // Estableciendo operacion a ser enviada al Servicio REST
                operacion = new Operacion();
                operacion.numero = Constantes.OPERACION_OBTENER_CLIENTE_PORDOCUMENTO;

                operacion.cliente = new Cliente();
                operacion.cliente.tipoDocumento = this.cboTipoDocumento.SelectedValue.ToString();
                operacion.cliente.nroDocumento = this.txtClienteNroDocumento.Text;

                // Instanciando y ejecutando llamada al ServicioREST
                ConexionREST conexionREST = new ConexionREST();
                contenidoXML = conexionREST.ejecutarOperacion(operacion);

                // Obteniendo Objeto de Error
                OperacionError operacionError = contenidoXML.DeserializarTo<OperacionError>();

                // Validar si hay error
                if (operacionError != null)
                {
                    Libreria.ShowMessageboxError(operacionError.descripcion);
                    return;
                }

                // Obteniendo Objeto de Cliente
                Cliente cliente = contenidoXML.DeserializarTo<Cliente>();

                // Limpiando datos del cliente anterior
                limpiarDatosCliente();

                // Si el cliente existe
                if (cliente != null)
                {
                    if (cliente.estado.Equals(Constantes.ESTADO_CODIGO_INACTIVO))
                    {
                        Libreria.ShowMessageboxExclamacion("Este cliente se encuentra en estado inactivo", this.Text);
                        return;
                    }

                    // Establecer su razon social
                    this.clienteActual = cliente;
                    this.txtClienteRazonSocial.Text = this.clienteActual.razonSocial;
                }
                else
                {
                    Libreria.ShowMessageboxExclamacion("El cliente buscado no existe", this.Text);
                    return;
                }
            }
            catch (Exception ex)
            {
                log.Error(ex.Message, ex);
                Libreria.MensajeError(ex, TITULO);
            }
            finally
            {
                Cursor.Current = Cursors.Default;
            }
        }

        private void limpiarDatosCliente()
        {
            // Limpiando datos del cliente anterior
            this.txtClienteRazonSocial.Text = string.Empty;
        }

        private void elegirProducto()
        {
            using (frmMantProducto frmMantProducto = new frmMantProducto())
            {
                frmMantProducto.formularioBusqueda = true;
                if (frmMantProducto.ShowDialog() == DialogResult.Cancel) { return; }

                this.producto = frmMantProducto.productoActual;

                // Mostrar los datos del producto
                this.txtProductoCodigo.Text = producto.codigo;
                this.txtProductoDescripcion.Text = string.Format(FORMATO_PRODUCTO_DESCRIPCION_DETALLADA, producto.nivelProducto.descripcion,
                                                                                                         producto.nivelTipo.descripcion,
                                                                                                         producto.nivelMaterial.descripcion,
                                                                                                         producto.nivelColor.descripcion);
                this.txtProductoPrecio.Text = producto.precioVentaMaximo.ToString(Constantes.FORMATO_DECIMAL);
            }

            obtenerItems(this.producto);
        }

        private void obtenerItems(Producto producto)
        {
            Operacion operacion = null;
            string contenidoXML = string.Empty;

            try
            {
                // Estableciendo operacion a ser enviada al Servicio REST
                operacion = new Operacion();
                operacion.numero = Constantes.OPERACION_LISTAR_ITEMS_PRODUCTO;

                operacion.producto = new Producto();
                operacion.producto.codigo = producto.codigo;

                // Instanciando y ejecutando llamada al ServicioREST
                ConexionREST conexionREST = new ConexionREST();
                contenidoXML = conexionREST.ejecutarOperacion(operacion);

                // Obteniendo Objeto de Error
                OperacionError operacionError = contenidoXML.DeserializarTo<OperacionError>();

                // Validar si hay error
                if (operacionError != null)
                {
                    Libreria.ShowMessageboxError(operacionError.descripcion);
                    return;
                }

                // Obteniendo Objeto de ListaItem
                ListaItem listaItem = contenidoXML.DeserializarTo<ListaItem>();

                // Se establece propiedad para evitar que genere nuevas columnas que no estan mapeadas en la grilla
                this.dgvListadoItems.AutoGenerateColumns = false;

                // Se establece la fuente de datos de la grilla
                this.dgvListadoItems.DataSource = listaItem.lista;

                pintarGrilla(this.dgvListadoItems);

                // Validar si el producto tiene items disponibles
                if (listaItem.lista.Count == 0)
                {
                    Libreria.ShowMessageboxExclamacion("El producto seleccionado, no tiene items disponibles", TITULO);
                }
            }
            catch (Exception ex)
            {
                log.Error(ex.Message, ex);
                Libreria.MensajeError(ex, TITULO);
            }
        }

        private void nuevo()
        {
            // Activando grupo para modificar campos
            this.grpDatos.Enabled = true;
            this.tbtnGrabar.Enabled = true;

            // Limpiando los datos del formulario
            //this.txtCodigo.Text = string.Empty;

            this.txtSerie.Text = string.Empty;
            this.txtNumero.Text = string.Empty;
            this.cboTipoDocVenta.SelectedIndex = 0;

            this.cboTipoDocumento.SelectedIndex = 0;
            this.txtClienteNroDocumento.Text = string.Empty;
            this.txtClienteRazonSocial.Text = string.Empty;

            this.txtProductoCodigo.Text = string.Empty;
            this.txtProductoDescripcion.Text = string.Empty;
            this.txtProductoPrecio.Text = Constantes.VALOR_CERO_DECIMAL;

            // Limpiando grilla de detalle de Items
            ListPersonalizada<Item> listaItem = (ListPersonalizada<Item>)this.dgvListadoItems.DataSource;
            ListPersonalizada<Item> listaItemsSeleccion = (ListPersonalizada<Item>)this.dgvListadoItemsSeleccionados.DataSource;

            if (listaItem != null)
            {
                listaItem.Clear();

                this.dgvListadoItems.DataSource = null;
                this.dgvListadoItems.DataSource = listaItem;
            }

            if (listaItemsSeleccion != null)
            {
                listaItemsSeleccion.Clear();

                this.dgvListadoItemsSeleccionados.DataSource = null;
                this.dgvListadoItemsSeleccionados.DataSource = listaItemsSeleccion;
            }


            // Estableciendo focus al control serie
            this.txtSerie.Focus();
        }

        private bool validarEntrada()
        {
            this.txtSerie.Text = this.txtSerie.Text.Trim();
            this.txtNumero.Text = this.txtNumero.Text.Trim();
            this.txtClienteRazonSocial.Text = this.txtClienteRazonSocial.Text.Trim();

            if (this.txtSerie.Text.Equals(string.Empty))
            {
                Libreria.CampoNecesario(this.txtSerie, "Debe ingresar el campo Serie", TITULO);
                return true;
            }

            if (this.txtNumero.Text.Equals(string.Empty))
            {
                Libreria.CampoNecesario(this.txtNumero, "Debe ingresar el campo Número", TITULO);
                return true;
            }

            if (this.cboTipoDocVenta.SelectedIndex == -1)
            {
                Libreria.CampoNecesario(this.cboMoneda, "Debe seleccionar un Tipo doc Venta", TITULO);
                return true;
            }

            if (this.cboMoneda.SelectedIndex == -1)
            {
                Libreria.CampoNecesario(this.cboMoneda, "Debe seleccionar una Moneda", TITULO);
                return true;
            }

            if (this.cboTipoDocumento.SelectedValue.ToString().Equals(Constantes.CODIGO_TIPO_VENTA_FACTURA))
            {
                if (this.txtClienteRazonSocial.Text.Equals(string.Empty))
                {
                    Libreria.CampoNecesario(this.txtClienteNroDocumento, "Debe elegir un Cliente", TITULO);
                    return true;
                }
            }

            ListPersonalizada<Item> listaItemsSeleccion = (ListPersonalizada<Item>)this.dgvListadoItemsSeleccionados.DataSource;

            if ((listaItemsSeleccion == null) || (listaItemsSeleccion.Count == 0))
            {
                Libreria.CampoNecesario(this.dgvListadoItemsSeleccionados, "Debe ingresar por lo menos un Item", TITULO);
                return true;
            }

            return false;
        }

        private void grabar()
        {
            Operacion operacion = null;
            string contenidoXML = string.Empty;

            try
            {
                if (validarEntrada()) { return; }

                // Solicitar confirmacion
                if (!Libreria.ShowMessageboxPregunta("¿Estas seguro de registrar la Venta?", TITULO)) { return; }

                // Estableciendo operacion a ser enviada al Servicio REST
                operacion = new Operacion();
                operacion.numero = Constantes.OPERACION_REGISTRAR_VENTA;

                operacion.venta = new Venta();
                operacion.venta.codVenta = Constantes.VALOR_CERO;

                // Estableciendo serie y numero de venta
                operacion.venta.serie = this.txtSerie.Text;
                operacion.venta.numero = this.txtNumero.Text;
                operacion.venta.notaCreditoNumero = this.txtNotaCreditoNumero.Text;
                operacion.venta.notaCreditoSerie = this.txtNotaCreditoSerie.Text;

                // Estableciendo cliente
                operacion.venta.cliente = new Cliente();
                operacion.venta.cliente.codCliente = this.clienteActual.codCliente;

                // Estableciendo el tipo de documento de venta
                operacion.venta.tipoDocumentoVenta = new TipoDocumentoVenta();
                operacion.venta.tipoDocumentoVenta.codigo = this.cboTipoDocVenta.SelectedValue.ToString();

                // Estableciendo tipo de moneda
                operacion.venta.moneda = new Moneda();
                operacion.venta.moneda.codigo = this.cboMoneda.SelectedValue.ToString();

                // Estableciendo forma de venta
                operacion.venta.formaVenta = new FormaVenta();
                operacion.venta.formaVenta.codigo = this.cboFormaVenta.SelectedValue.ToString();

                //estableciendo tienda
                operacion.venta.tienda = new Tienda();
                operacion.venta.tienda.codigo = ParametrosAplicacion.TIENDA_ACTUAL.codigo;

                //-----------------------------------------------------------------------
                //El Precio ya incluye el IGV, en el momento que se decida si el cliente quiere factura o boleta se define el calculo.
                //-----------------------------------------------------------------------
                // Calculando el total a pagar
                operacion.venta.total = Math.Round(this.txtTotal.Text.ToDouble(), 2);

                //obteniendo el monto total
                operacion.venta.subTotal = Math.Round((operacion.venta.total) / (1 + this.igvActual), 2);

                //calculando el IGV 
                operacion.venta.igv = Math.Round(operacion.venta.total - operacion.venta.subTotal, 2);

                //calculando el saldo, que como no se ha pagado es igual al total
                operacion.venta.saldo = operacion.venta.total;
                //-----------------------------------------------------------------------

                // Capturando listado de items agregados
                ListPersonalizada<Item> listaItemAgregados = (ListPersonalizada<Item>)this.dgvListadoItemsSeleccionados.DataSource;

                //-----------------------------------------------------------------------
                // Cambio
                //armar lista de productos
                ListaProducto listaProductoResumen = new ListaProducto();
                //navegar en toda la lista de items
                foreach (Item item in listaItemAgregados)
                {
                    //navegar en la lista de productos
                    Boolean bNuevo = true;
                    foreach (Producto producto in listaProductoResumen.lista)
                    //Si el producto no está en la lista, se agrega
                    {
                        if (producto.codigo.Equals(item.producto.codigo))
                        {
                            bNuevo = false;
                            break;
                        }
                    }
                    if (bNuevo)
                    {
                        listaProductoResumen.add(item.producto);
                    }
                }

                ListaLineaVenta listaLineaVenta = new ListaLineaVenta();
                LineaVenta lineaVenta = null;

                foreach (Producto producto in listaProductoResumen.lista)
                {
                    lineaVenta = new LineaVenta();

                    lineaVenta.codVenta = Constantes.VALOR_CERO;
                    lineaVenta.numeroLinea = Constantes.VALOR_CERO;

                    lineaVenta.producto = new Producto { codigo = producto.codigo };
                    lineaVenta.precio = producto.precioVentaTransaccion;

                    //---------------------------------------------------------------
                    //var listadoItem = (from d in listaItemAgregados
                    //                   where d.producto.codigo.Equals(producto.codigo)
                    //                   select d).ToList<Item>();
                    //----------------------------------------------------------------
                    ListaItem listadoItem = new ListaItem();
                    foreach (Item itemAgregado in listaItemAgregados)
                    {
                        if (itemAgregado.producto.codigo.Equals(producto.codigo))
                            listadoItem.add(itemAgregado);
                    }
                    //----------------------------------------------------------------
                    ListaLineaVentaItem listaLineaVentaItem = new ListaLineaVentaItem();
                    LineaVentaItem lineaVentaItem = null;

                    foreach (Item item in listadoItem.lista)
                    {
                        lineaVentaItem = new LineaVentaItem();
                        //lineaVentaItem.item = new Item { codItem = item.codItem, estado = item.estado };
                        lineaVentaItem.item = new Item();
                        lineaVentaItem.item = item;
                        lineaVentaItem.codVenta = Constantes.VALOR_CERO;
                        lineaVentaItem.numeroLinea = Constantes.VALOR_CERO;

                        // Agregando item al detalle de linea de venta
                        listaLineaVentaItem.add(lineaVentaItem);
                    }

                    // Estableciendo listado de items
                    lineaVenta.listaLineaVentaItem = listaLineaVentaItem;

                    // Estableciendo la cantidad de items
                    lineaVenta.cantidad = listaLineaVentaItem.size().ToString();

                    // Agregando linea a la venta
                    listaLineaVenta.add(lineaVenta);
                }

                // Estableciendo listado detalle de venta
                operacion.venta.listaLineaVenta = listaLineaVenta;

                // Estableciendo usuario de registro
                operacion.venta.usuario = new Usuario();
                operacion.venta.usuario = ParametrosAplicacion.USUARIO_ACTUAL;
                

                // Estableciendo estado y fecha
                operacion.venta.estado = Constantes.ESTADO_VENTA_PENDIENTE;
                operacion.venta.fechaRegistro = DateTime.Now.ToString(Constantes.FORMATO_FECHAHORA);

                // Instanciando y ejecutando llamada al ServicioREST
                ConexionREST conexionREST = new ConexionREST();
                contenidoXML = conexionREST.ejecutarOperacion(operacion);

                // Obteniendo Objeto de Error
                OperacionError operacionError = contenidoXML.DeserializarTo<OperacionError>();

                // Validar si hay error
                if (operacionError != null)
                {
                    Libreria.ShowMessageboxError(operacionError.descripcion);
                    return;
                }

                OperacionResultado operacionResultado = contenidoXML.DeserializarTo<OperacionResultado>();

                if ((operacionResultado != null) &&
                    (operacionResultado.esOK.Equals(Constantes.SI)))
                {
                    //this.txtCodigo.Text = operacionResultado.codigoGenerado;
                    Libreria.ShowMessageboxInfo("Venta guardado correctamente", TITULO);
                }
                else
                {
                    Libreria.ShowMessageboxError("No se guardo los datos", TITULO);
                    return;
                }

                // Estableciendo los estados de los botones
                this.grpDatos.Enabled = false;
                this.tbtnGrabar.Enabled = false;
            }
            catch (Exception ex)
            {
                log.Error(ex.Message, ex);
                Libreria.MensajeError(ex, TITULO);
            }
        }

        private Double cargarIgv()
        {
            Double igv = 0;
            Operacion operacion = null;
            ListaParametro listaParametro = null;
            string contenidoXML = string.Empty;

            // Estableciendo operacion a ser enviada al Servicio REST
            operacion = new Operacion();
            operacion.numero = Constantes.OPERACION_LISTAR_PARAMETROS;

            // Instanciando y ejecutando llamada al ServicioREST
            ConexionREST conexionREST = new ConexionREST();
            contenidoXML = conexionREST.ejecutarOperacion(operacion);

            // Obteniendo Objeto de Error
            OperacionError operacionError = contenidoXML.DeserializarTo<OperacionError>();

            // Validar si hay error
            if (operacionError != null)
            {
                Libreria.ShowMessageboxError(operacionError.descripcion);
                return 0;
            }

            // Obteniendo Objeto de Nivel
            listaParametro = contenidoXML.DeserializarTo<ListaParametro>();

            foreach (Parametro parametro in listaParametro.lista)
            {
                switch (parametro.codigo)
                {
                    case Constantes.CODIGO_PARAMETRO_IGV:
                        igv = parametro.valor.ToDouble();
                        break;
                }
            }
            return igv;
        }

        private void pintarGrilla(DataGridView grilla)
        {
            ListPersonalizada<Item> listaItems = null;
            listaItems = (ListPersonalizada<Item>)grilla.DataSource;

            if (listaItems != null)
            {
                for (int i = 0; i < listaItems.Count; i++)
                {
                    var item = listaItems[i];
                    grilla.Rows[i].Cells[2].Value = item.producto.codProductoProveedor;
                    grilla.Rows[i].Cells[3].Value = item.producto.descripcion;
                    grilla.Rows[i].Cells[4].Value = item.producto.precioVentaTransaccion; //AGREGADO K
                }
            }
        }

        private bool validarItemRepetido(string codItem)
        {
            bool resultato = false;

            // Obteniendo lista de items seleccionados
            ListPersonalizada<Item> listaItemsSeleccion = (ListPersonalizada<Item>)this.dgvListadoItemsSeleccionados.DataSource;

            if (listaItemsSeleccion != null)
            {
                foreach (Item item in listaItemsSeleccion)
                {
                    if (item.codItem.Equals(codItem))
                    {
                        resultato = true;
                        break;
                    }
                }
            }

            return resultato;
        }

        private bool validarAgregar()
        {
            this.txtProductoCodigo.Text = this.txtProductoCodigo.Text.Trim();
            this.txtProductoDescripcion.Text = this.txtProductoDescripcion.Text.Trim();
            this.txtProductoPrecio.Text = this.txtProductoPrecio.Text.Trim();

            if (this.txtProductoDescripcion.Text.Equals(string.Empty))
            {
                Libreria.ShowMessageboxExclamacion("Debe seleccionar un producto para agregar", TITULO);
                return true;
            }

            if (this.txtProductoPrecio.Text.Equals(string.Empty))
            {
                Libreria.CampoNecesario(this.txtProductoPrecio, "Debe ingresar el precio del producto", TITULO);
                return true;
            }

            if ((this.txtProductoPrecio.Text.EsEnteroConSigno()) &&
                (this.txtProductoPrecio.Text.ToDouble() < this.producto.precioVentaMinimo ||
                 this.txtProductoPrecio.Text.ToDouble() > this.producto.precioVentaMaximo))
            {
                Libreria.CampoNecesario(this.txtProductoPrecio, "Debe ingresar una precio válido", TITULO);
                return true;
            }

            return false;
        }

        private void agregarItem()
        {
            ListPersonalizada<Item> listaItems = null;
            ListPersonalizada<Item> listaItemsSeleccion = null;

            try
            {
                // Validar que el producto haya sido elegido
                if (validarAgregar()) { return; }

                // Capturando fuentes de datos de las grillas
                listaItems = (ListPersonalizada<Item>)this.dgvListadoItems.DataSource;
                listaItemsSeleccion = (ListPersonalizada<Item>)this.dgvListadoItemsSeleccionados.DataSource;

                if (listaItemsSeleccion == null) { listaItemsSeleccion = new ListPersonalizada<Item>(); }

                // Validar si el producto tiene items disponibles
                if (listaItems.Count == 0)
                {
                    Libreria.ShowMessageboxExclamacion("El producto actual, no tiene items disponibles", TITULO);
                    return;
                }

                // Item Seleccionado
                Item itemSeleccionado = listaItems[this.dgvListadoItems.CurrentRow.Index];

                // Valida si el item ya fue agregado
                if (validarItemRepetido(itemSeleccionado.codItem))
                {
                    Libreria.CampoNecesario(this.dgvListadoItems, "Este item ya se encuentra asociado", TITULO);
                    return;
                }

                // Instanciando item a agregar
                Item itemAgregar = new Item();
                itemAgregar.codItem = itemSeleccionado.codItem;

                // Estableciendo producto del item
                itemAgregar.producto = new Producto();
                itemAgregar.producto.codigo = itemSeleccionado.producto.codigo;
                itemAgregar.producto.descripcion = itemSeleccionado.producto.descripcion;
                itemAgregar.producto.codProductoProveedor = itemSeleccionado.producto.codProductoProveedor;

                // Establecer el precio de venta en el dato del precio de Venta Transaccion
                itemAgregar.producto.precioVentaTransaccion = Convert.ToDouble(this.txtProductoPrecio.Text);
                itemAgregar.precioVenta = Convert.ToDouble(this.txtProductoPrecio.Text);

                // Establecer el estado vendido del item
                itemAgregar.estado = Constantes.ESTADO_ITEM_VENDIDO;

                // Agregando item a listado de items seleccionados
                listaItemsSeleccion.Add(itemAgregar);

                // Se establece propiedad para evitar que genere nuevas columnas que no estan mapeadas en la grilla
                this.dgvListadoItemsSeleccionados.AutoGenerateColumns = false;

                // Actualizando en grilla
                this.dgvListadoItemsSeleccionados.DataSource = null;
                this.dgvListadoItemsSeleccionados.DataSource = listaItemsSeleccion;

                pintarGrilla(this.dgvListadoItemsSeleccionados);

                // Recalcular total
                calcularTotal();
            }
            catch (Exception ex)
            {
                log.Error(ex.Message, ex);
                Libreria.MensajeError(ex, TITULO);
            }
        }

        private void quitarItem()
        {
            ListPersonalizada<Item> listaItemsSeleccion = null;
            try
            {
                listaItemsSeleccion = (ListPersonalizada<Item>)this.dgvListadoItemsSeleccionados.DataSource;

                if (listaItemsSeleccion != null && listaItemsSeleccion.Count > 0)
                {
                    // Item Seleccionado
                    Item itemSeleccionado = listaItemsSeleccion[this.dgvListadoItemsSeleccionados.CurrentRow.Index];

                    listaItemsSeleccion.Remove(itemSeleccionado);

                    // Actualizando en grilla
                    this.dgvListadoItemsSeleccionados.DataSource = null;
                    this.dgvListadoItemsSeleccionados.DataSource = listaItemsSeleccion;

                    pintarGrilla(this.dgvListadoItemsSeleccionados);

                    // Recalcular total
                    calcularTotal();
                }
            }
            catch (Exception ex)
            {
                log.Error(ex.Message, ex);
                Libreria.MensajeError(ex, TITULO);
            }
        }

        private void calcularTotal()
        {
            ListPersonalizada<Item> listaItem = (ListPersonalizada<Item>)this.dgvListadoItemsSeleccionados.DataSource;

            // Obteniendo el monto total
            double total = (from d in listaItem
                            select d.producto.precioVentaTransaccion).Sum();

            // Mostrando el monto total
            this.txtTotal.Text = total.ToString(Constantes.FORMATO_DECIMAL);
        }

        private void salir()
        {
            this.Close();
        }
        #endregion

        private void cboFormaVenta_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void txtNumero_TextChanged(object sender, EventArgs e)
        {

        }
    }
}
